﻿using System;
using System.Linq;
using Raven.Client;
using TimeTracker.Entities;

namespace TimeTracker.Persistence
{
    public static class EntitiesExtensions
    {
        public static Client GetClientById(this IDocumentSession session, string id)
        {
            if (!id.IsEntityId())
                throw new ArgumentException(string.Format("The id '{0}' is not a raven accepted id"));

            var client = session.Load<Client>(id);
            if (client == null)
                throw new ArgumentException(string.Format("the client with id '{0}' does not exists.", id), "id");

            return client;
        }

        public static bool TryGetClientById(this IDocumentSession session, string id, out Client client)
        {
            if (!id.IsEntityId())
                throw new ArgumentException("id is not a raven id", "id");

            client = session.Load<Client>(id);
            return client != null;
        }

        public static Client GetClientByName(this IDocumentSession session, string name)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("name cannot be null, empty or whitespace.", "name");

            var query = from u in session.Query<Client>()
                        where u.Name == name
                        select u;

            var client = query.FirstOrDefault();
            if (client == null)
                throw new ArgumentException(string.Format("the client with name '{0}' does not exists.", name), "name");

            return client;
        }     

        public static bool TryGetClientByName(this IDocumentSession session, string name, out Client client)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("name cannot be null, empty or whitespace.", "name");

            var query = from u in session.Query<Client>()
                        where u.Name == name
                        select u;

            client = query.FirstOrDefault();

            return client != null;
        }      

        public static Project GetProjectById(this IDocumentSession session, string id)
        {
            if (!id.IsEntityId())
                throw new ArgumentException(string.Format("The id '{0}' is not a raven accepted id"));

            var project = session.Load<Project>(id);
            if (project == null)
                throw new ArgumentException(string.Format("the project with id '{0}' does not exists.", id), "id");

            return project;
        }

        public static bool TryGetProjectById(this IDocumentSession session, string id, out Project project)
        {
            if (!id.IsEntityId())
                throw new ArgumentException("id is not a raven id", "id");

            project = session.Load<Project>(id);
            return project != null;
        }

        public static Project GetProjectByName(this IDocumentSession session, string name)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("name cannot be null, empty or whitespace.", "name");

            var query = from u in session.Query<Project>()
                        where u.Name == name
                        select u;

            var project = query.FirstOrDefault();
            if (project == null)
                throw new ArgumentException(string.Format("the project with name '{0}' does not exists.", name), "name");

            return project;
        }

        public static bool TryGetProjectByName(this IDocumentSession session, string name, out Project project)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("name cannot be null, empty or whitespace.", "name");

            var query = from u in session.Query<Project>()
                        where u.Name == name
                        select u;

            project = query.FirstOrDefault();
            return project != null;
        }      

        public static User GetUserById(this IDocumentSession session, string id)
        {
            if (!id.IsEntityId())
                throw new ArgumentException(string.Format("The id '{0}' is not a raven accepted id"));

            var user = session.Load<User>(id);
            if (user == null)
                throw new ArgumentException(string.Format("the user with id '{0}' does not exists.", id), "id");

            return user;
        }

        public static bool TryGetUserById(this IDocumentSession session, string id, out User user)
        {
            if (!id.IsEntityId())
                throw new ArgumentException("id is not a raven id", "id");

            user = session.Load<User>(id);
            return user != null;
        }

        public static User GetUserByEmail(this IDocumentSession session, string email)
        {
            if (string.IsNullOrWhiteSpace(email))
                throw new ArgumentException("email is not a valid string", "email");

            var query = from u in session.Query<User>()
                        where u.Email == email
                        select u;

            var user = query.FirstOrDefault();
            if (user == null)
                throw new ArgumentException(string.Format("the user with email '{0}' does not exists.", email), "email");

            return user;
        }

        public static bool TryGetUserByEmail(this IDocumentSession session, string email, out User user)
        {
            if (string.IsNullOrWhiteSpace(email))
                throw new ArgumentException("email is not a valid string", "email");

            var query = from u in session.Query<User>()
                        where u.Email == email
                        select u;

            user = query.FirstOrDefault();
            return user != null;
        }

        public static Entry GetEntryById(this IDocumentSession session, string id)
        {
            if (!id.IsEntityId())
                throw new ArgumentException(string.Format("The id '{0}' is not a raven accepted id"));

            var user = session.Load<Entry>(id);
            if (user == null)
                throw new ArgumentException(string.Format("the entry with id '{0}' does not exists.", id), "id");

            return user;
        }

        public static bool TryGetEntryById(this IDocumentSession session, string id, out Entry entry)
        {
            if (!id.IsEntityId())
                throw new ArgumentException("id is not a raven id", "id");

            entry = session.Load<Entry>(id);
            return entry != null;
        }
    }
}
